package com.xiyu.service.service.infra.devops;

import com.xiyu.service.dal.websocket.serverInit.ServerInitMessage;
import com.xiyu.service.enums.common.UserTypeEnum;
import com.xiyu.service.framework.websocket.core.sender.WebSocketMessageSender;
import com.xiyu.service.vo.infra.devops.server.ServerListQueryOutput;
import com.xiyu.service.vo.infra.devops.server.ServerSingleGetOutput;
import com.xiyu.service.vo.infra.devops.server.ServerUpdateInput;
import com.xiyu.service.vo.infra.devops.server.ServerCreateInput;
import com.xiyu.service.model.devops.server.DevopsServer;
import com.xiyu.service.repository.devops.server.DevopsServerRepository;
import com.xiyu.service.vo.infra.devops.server.ServerPageQueryOutput;
import com.xiyu.service.vo.infra.devops.server.ServerPageQueryInput;
import com.jcraft.jsch.*;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;

import java.io.*;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.util.entity.EntityUtils;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.infra.devops.ServerConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.infra.devops.ServerErrorCode.*;
import static com.xiyu.service.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

/**
 * 服务器管理 Service 实现类
 */
@Service
@Validated
public class ServerServiceImpl implements ServerService {

    @Resource
    private DevopsServerRepository devopsServerRepository;

    @Resource
    private WebSocketMessageSender webSocketMessageSender;




    @Override
    public PageResult<ServerPageQueryOutput> pageQuery(ServerPageQueryInput inputVO) {
        Page<DevopsServer> pageDevopsServer = devopsServerRepository.pageQuery(inputVO);
        List<ServerPageQueryOutput> listDevopsServer = ServerConvert.INSTANCE.pageQueryOutputConvert(pageDevopsServer.getRows());
        return new PageResult<>(listDevopsServer, pageDevopsServer.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(ServerCreateInput inputVO) {
        DevopsServer newDevopsServer = ServerConvert.INSTANCE.createInputConvert(inputVO);
        newDevopsServer = devopsServerRepository.insert(newDevopsServer);
        return newDevopsServer.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(ServerUpdateInput inputVO) {
        Optional<DevopsServer> optionalOldDevopsServer = devopsServerRepository.findById(inputVO.getId());
        if(optionalOldDevopsServer.isEmpty()){
            throw exception(DEVOPS_SERVER_NOT_EXIST);
        }
        DevopsServer updateDevopsServer = ServerConvert.INSTANCE.updateInputConvert(inputVO);
        if (!EntityUtils.isEquals(optionalOldDevopsServer.get(), updateDevopsServer))
            devopsServerRepository.update(updateDevopsServer);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleted(Long id) {
        Optional<DevopsServer> optionalOldDevopsServer = devopsServerRepository.findById(id);
        if(optionalOldDevopsServer.isEmpty()){
            throw exception(DEVOPS_SERVER_NOT_EXIST);
        }
        devopsServerRepository.deleteById(id);
        return true;
    }

    @Override
    public ServerSingleGetOutput singleGet(Long id) {
        Optional<DevopsServer> optionDevopsServer = devopsServerRepository.findById(id);
        if(optionDevopsServer.isEmpty()){
            throw exception(DEVOPS_SERVER_NOT_EXIST);
        }
        return ServerConvert.INSTANCE.singleGetOutputConvert(optionDevopsServer.get());

    }

    @Override
    public List<ServerListQueryOutput> listQuery() {
        List<DevopsServer> listDevopsServer = devopsServerRepository.listQuery();
        return ServerConvert.INSTANCE.listQueryOutputConvert(listDevopsServer);

    }

    @Override
    public void init(Long id){
        DevopsServer devopsServer = devopsServerRepository.findNullable(id);
        if(devopsServer == null){
            throw exception(DEVOPS_SERVER_NOT_EXIST);
        }
        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession("root", devopsServer.ip(), 22);
            session.setPassword(devopsServer.serverPassword());
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            uploadInstallFile(session);

            execSh(session, devopsServer);

            uploadSettingFile(session);
            session.disconnect();

        } catch (Exception e) {
            webSocketSendMessage("error", e.getMessage());
            e.printStackTrace();
        }
    }

    private void execSh(Session session, DevopsServer devopsServer) throws JSchException, IOException {
        // 打开 Shell 通道
        Channel channel = session.openChannel("shell");
        OutputStream inputToShell = channel.getOutputStream();
        InputStream outputFromShell = channel.getInputStream();

        // 启动通道
        channel.connect();

        // 发送命令
        PrintWriter writer = new PrintWriter(inputToShell, true);
        writer.println("export MYSQL_ROOT_PASSWORD=\"" + devopsServer.databasePassword() + "\"");
        writer.println("bash ~/install_software.sh");
        writer.println("exit"); // 退出 Shell
//
//        // 执行脚本
//        Channel channel = session.openChannel("exec");
//
//        ((ChannelExec) channel).setCommand("export MYSQL_ROOT_PASSWORD=\"" + devopsServer.databasePassword() + "\"" + " && bash ~/install_software.sh");// 执行脚本命令
//
//        // 获取输出流
//        InputStream inputStream = channel.getInputStream();
//        channel.connect();

        // 使用 BufferedReader 按行读取输出
        System.out.println("执行结果：");
        BufferedReader reader = new BufferedReader(new InputStreamReader(outputFromShell));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line); // 按行输出
            webSocketSendMessage("success", line);
        }

//        // 等待通道关闭
//        if (channel.isClosed()) {
//            System.out.println("退出状态: " + channel.getExitStatus());
//            webSocketSendMessage("success", "退出状态: " + channel.getExitStatus());
//        }

        // 关闭通道和会话
        channel.disconnect();
    }

    private void uploadInstallFile(Session session) throws JSchException, SftpException {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("serverInit/install_software.sh");
        Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp sftpChannel = (ChannelSftp) channel;
        // 上传文件
        sftpChannel.put(inputStream, "/root/install_software.sh");
        webSocketSendMessage("success", "安装文件上传成功");
        sftpChannel.exit();


    }

    private void uploadSettingFile(Session session) throws JSchException, SftpException, IOException {
        Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp sftpChannel = (ChannelSftp) channel;
        // 上传文件
        InputStream nginxStream = getClass().getClassLoader().getResourceAsStream("serverInit/nginx.conf");
        sftpChannel.put(nginxStream, "/etc/nginx/nginx.conf");

        webSocketSendMessage("success", "配置文件上传成功");

        sftpChannel.exit();
        channel.disconnect();


    }

    private void webSocketSendMessage(String error, String message){
        webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), getLoginUserId(),
                "server-init", new ServerInitMessage().setStatus(error).setMessage(message ));
    }

}
